home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / file / managers / mc-3.2 / mc-3 / mc-3.2.1 / xv / xvicon.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-17  |  15.3 KB  |  487 lines

  1. /* XView Onroot Icon from Pixmap creation.
  2.    Copyright (C) 1995 Jakub Jelinek.
  3.    
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2 of the License, or
  7.    (at your option) any later version.
  8.    
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. #include <config.h>
  19.  
  20. #ifdef HAVE_XPM_SHAPE
  21.  
  22. #include <stdio.h>
  23. #include <X11/Xlib.h>
  24. #include <X11/Xutil.h>
  25. #include <X11/extensions/shape.h>
  26. #include <xview/xview.h>
  27. #include <xview/frame.h>
  28. #include <xview/dragdrop.h>
  29. #include <xview/font.h>
  30. #include <xview/defaults.h>
  31. #include "util.h"
  32. #include "mad.h"
  33.  
  34. #include "xvmain.h"
  35. #include "xvicon.h"
  36. #include "xvscreen.h"
  37.  
  38. /* XPM */
  39. static char *file_xpm[] = {
  40. /* width height ncolors chars_per_pixel */
  41. "32 32 5 1",
  42. /* colors */
  43. "` c black",
  44. "a c gray",
  45. "c c black",
  46. "d s none c none",
  47. "e c white",
  48. /* pixels */
  49. "dddd``````````````````dddddddddd",
  50. "dddd`eeeeeeeeeeeeeeee``ddddddddd",
  51. "dddd`eeeeeeeeeeeeeeee`a`dddddddd",
  52. "dddd`eeeeeeeeeeeeeeee`aa`ddddddd",
  53. "dddd`eeeeeeeeeeeeeeee`aaa`dddddd",
  54. "dddd`eeeeeeeeeeeeeeee`aaaa`ddddd",
  55. "dddd`eeeeeeeeeeeeeeee```````dddd",
  56. "dddd`eeeeeeeeeeeeeeeeeaaaaa`cddd",
  57. "dddd`eeeeeeeeeeeeeeeeeeaaaa`cddd",
  58. "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
  59. "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
  60. "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
  61. "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
  62. "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
  63. "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
  64. "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
  65. "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
  66. "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
  67. "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
  68. "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
  69. "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
  70. "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
  71. "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
  72. "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
  73. "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
  74. "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
  75. "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
  76. "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
  77. "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
  78. "dddd`eeeeeeeeeeeeeeeeeeeeee`cddd",
  79. "dddd````````````````````````cddd",
  80. "dddddccccccccccccccccccccccccddd"
  81. };
  82.  
  83. extern Display *dpy;
  84. static Screen *screen;
  85. #define root XRootWindowOfScreen(screen)
  86. static Colormap colormap;
  87. extern Frame mcframe;
  88. extern Dlg_head *midnight_dlg;
  89.  
  90. static struct {
  91.     Frame frame;
  92.     int btn_down_x, btn_down_y;
  93.     struct timeval prev_time;
  94. } click_info = { XV_NULL, 0, 0, {0, 0}};
  95. static int xv_icon_grab = 0, xv_icon_drag = 0;
  96. static int wait_for_btnup = 0;
  97. static GC xor_gc;
  98. static int last_x, last_y, offset_x, offset_y;
  99. static xv_icondep_frame = XV_NULL;
  100. static char *xv_icondep_free = NULL;
  101.  
  102. static void draw_borderrect (Window win, Xv_window xv_win, int x, int y)
  103. {
  104.     int width, height;
  105.     
  106.     width = xv_get (xv_win, XV_WIDTH);
  107.     height = xv_get (xv_win, XV_HEIGHT);
  108.     
  109.     XDrawRectangle (dpy, win, xor_gc, x, y, width, height);
  110. }
  111.  
  112. struct xviconruncommand {
  113.     char *filename;
  114.     char *action;
  115.     char *drops;
  116. };
  117.  
  118. void xvIconRunCommand (struct xviconruncommand *xirc)
  119. {
  120.     regex_command (x_basename (xirc->filename), xirc->action, xirc->drops);
  121.     free (xirc->filename);
  122.     free (xirc->action);
  123.     if (xirc->drops != NULL)
  124.         free (xirc->drops);
  125.     free (xirc);
  126. }
  127.  
  128. void XvIconRunCommand (Frame frame, char *action, char *drops)
  129. {
  130.     XpmIcon *icon = (XpmIcon *) xv_get (frame, WIN_CLIENT_DATA);
  131.     struct xviconruncommand *xirc = (struct xviconruncommand *)
  132.         xmalloc (sizeof (struct xviconruncommand), "XvIconRunCommand");
  133.     
  134.     xirc->filename = strdup (icon->filename);
  135.     xirc->action = strdup (action);
  136.     if (drops != NULL)
  137.         xirc->drops = strdup (drops);
  138.     else
  139.         xirc->drops = NULL;
  140.     
  141.     xv_post_proc (midnight_dlg, (void (*)(void *))xvIconRunCommand, 
  142.         (void *) xirc);
  143. }
  144.  
  145. void XvIconDepMenu (Menu menu, Menu_item item)
  146. {
  147.     char *p = (char *) xv_get (item, MENU_STRING);
  148.     
  149.     if (!strcmp (p, "Close")) {
  150.     DeleteXpmIcon ((XpmIcon *) xv_get (xv_icondep_frame, WIN_CLIENT_DATA));
  151.     xv_destroy_safe (xv_icondep_frame);
  152.     XFlush (dpy);
  153.     } else {
  154.         XvIconRunCommand (xv_icondep_frame, p, NULL);
  155.     }
  156.     if (xv_icondep_free)
  157.         free (xv_icondep_free);
  158. }
  159.  
  160. void XpmIconEvent (Xv_window frame, Event *event)
  161. {
  162.     if (xv_icon_drag) {
  163.         if (event_action (event) == LOC_DRAG) {
  164.             draw_borderrect (root, frame, last_x, last_y);
  165.             last_x = event_x (event) - offset_x;
  166.             last_y = event_y (event) - offset_y;
  167.             draw_borderrect (root, frame, last_x, last_y);
  168.             return;
  169.         } else if (event_is_button (event)) {
  170.             if (event_is_down (event))
  171.                 return;
  172.         } else if (!event_is_iso (event))
  173.             return;
  174.         draw_borderrect (root, frame, last_x, last_y);
  175.         last_x = event_x (event) - offset_x;
  176.         last_y = event_y (event) - offset_y;
  177.         xv_set (frame,
  178.             XV_X, last_x,
  179.             XV_Y, last_y,
  180.             NULL);
  181.         xv_icon_drag = 0;
  182.         xv_icon_grab = 0;
  183.         XFreeGC (dpy, xor_gc);
  184.         return;
  185.     } else if (xv_icon_grab) {
  186.         if (wait_for_btnup) {
  187.             if (event_action (event) == LOC_DRAG) {
  188.                 static int threshold;
  189.                 static int dist_x, dist_y;
  190.                 
  191.                 if (threshold == 0)
  192.                     threshold = defaults_get_integer (
  193.                         "mxc.clickmovethreshold",
  194.                         "Mxc.ClickMoveThreshold", 10);
  195.                         
  196.                 dist_x = event_x (event) - click_info.btn_down_x;
  197.                 if (dist_x < 0)
  198.                     dist_x = - dist_x;
  199.                 dist_y = event_y (event) - click_info.btn_down_y;
  200.                 if (dist_y < 0)
  201.                     dist_y = - dist_y;
  202.                 if (!xv_icon_drag && (dist_x > threshold || dist_y > threshold ||
  203.                     event_ctrl_is_down (event) || event_shift_is_down (event))) {
  204.                         xor_gc = XCreateGC (dpy, xv_get (frame, XV_XID), 0, 0);
  205.                         XSetForeground (dpy, xor_gc, xv_get (frame, WIN_FOREGROUND_COLOR));
  206.                         XSetFunction (dpy, xor_gc, GXxor);
  207.                         XSetLineAttributes (dpy, xor_gc, 2, LineSolid, CapNotLast, JoinRound);
  208.                         last_x = xv_get (frame, XV_X);
  209.                         last_y = xv_get (frame, XV_Y);
  210.                         offset_x = event_x (event) - last_x;
  211.                         offset_y = event_y (event) - last_y;
  212.                         draw_borderrect (root, frame, last_x, last_y);
  213.             xv_icon_drag = 1;
  214.                 }
  215.                 return;        
  216.             }
  217.             if (event_is_button (event) && event_is_down (event)) {
  218.                 return;
  219.             }
  220.             if (event_action (event) == ACTION_SELECT) {
  221.                 if (is_dbl_click (&click_info.prev_time, &event_time (event))) {
  222.                     click_info.prev_time.tv_sec = 0;
  223.                     click_info.prev_time.tv_usec = 0;
  224.             XvIconRunCommand (frame, "Open", NULL);
  225.                 } else {
  226.                     click_info.prev_time = event_time (event);
  227.                 }
  228.                 xv_icon_grab = 0;
  229.                 return;
  230.             }
  231.             if (event_action (event) == ACTION_ADJUST) {
  232.                 xv_icon_grab = 0;
  233.                 return;
  234.             }
  235.             if (!event_is_button (event) && !event_is_iso (event))
  236.                 return;
  237.             xv_icon_grab = 0;
  238.             return;
  239.         }
  240.     }
  241.     switch (event_action (event)) {
  242.         case ACTION_DRAG_PREVIEW:
  243.         return;
  244.         case ACTION_DRAG_COPY:
  245.         case ACTION_DRAG_MOVE:
  246.         case ACTION_DRAG_LOAD:
  247.             {
  248.         Xv_drop_site ds;
  249.         Selection_requestor sel = (Selection_requestor) 
  250.             xv_get (frame, XV_KEY_DATA, KEY_DATA_SELREQ);
  251.         
  252.         if ((ds = dnd_decode_drop (sel, event)) != XV_ERROR) {
  253.             int length, format;
  254.             char *p, *q;
  255.                 
  256.             xv_set (sel, SEL_TYPE, XA_STRING, NULL);
  257.             q = (char *) xv_get (sel, SEL_DATA, &length, &format);
  258.             if (length != SEL_ERROR) {
  259.                 XvIconRunCommand (frame, "Drop", q);
  260.                 free (q);
  261.             }
  262.             xv_set (sel, SEL_TYPE_NAME, "_SUN_SELECTION_END", 0);
  263.             xv_get (sel, SEL_DATA, &length, &format);
  264.             dnd_done (sel);
  265.         }
  266.             }
  267.             return;
  268.         case ACTION_HELP:
  269.             if (event_is_down (event)) {
  270.             }
  271.             return;
  272.         case ACTION_MENU:
  273.             if (event_is_down (event)) {
  274.                 static Menu menu = XV_NULL;
  275.                 char *p, *q, c;
  276.                 char *filename;
  277.                 
  278.                 if (menu != XV_NULL)
  279.                     xv_destroy (menu);
  280.  
  281.         filename = ((XpmIcon *) xv_get (frame, WIN_CLIENT_DATA))->filename;
  282.                 menu = (Menu) xv_create (XV_NULL, MENU,
  283.                     MENU_NOTIFY_PROC, XvIconDepMenu,
  284.                     MENU_TITLE_ITEM, x_basename (filename),
  285.                     MENU_STRINGS, "Close", "Open", "View", "Edit", NULL,
  286.                     NULL);
  287.                 p = regex_command (x_basename (filename), NULL, NULL);
  288.                 if (p != NULL) {
  289.                     for (;;) {
  290.                         while (*p == ' ' || *p == '\t')
  291.                             p++;
  292.                         if (!*p)
  293.                             break;
  294.                         q = p;
  295.                         while (*q && *q != ' ' && *q != '\t')
  296.                             q++;
  297.                         c = *q;
  298.                         *q = 0;
  299.                         xv_set (menu,
  300.                             MENU_ITEM,
  301.                                 MENU_STRING, p,
  302.                                 NULL,
  303.                             NULL);
  304.                         if (!c)
  305.                             break;
  306.                         p = q + 1;
  307.                     }
  308.                 }
  309.                 xv_icondep_frame = frame;
  310.                 xv_icondep_free = p;
  311.                 menu_show (menu, frame, event, NULL);
  312.             }
  313.             return;
  314.         case ACTION_SELECT:
  315.         case ACTION_ADJUST:
  316.             if (event_is_down (event)) {
  317.            if (click_info.frame != frame) {
  318.                     click_info.frame = frame;
  319.                     click_info.prev_time.tv_sec = 0;
  320.                     click_info.prev_time.tv_usec = 0;
  321.                 }
  322.                 click_info.btn_down_x = event_x (event);
  323.                 click_info.btn_down_y = event_y (event);
  324.                 wait_for_btnup = 1;
  325.                 xv_icon_grab = 1;
  326.             }
  327.     }
  328. }
  329.  
  330. XpmIcon *CreateXpmIcon (char *iconname, int x, int y, char *title)
  331. {
  332.     int ErrorStatus;
  333.     Window win;
  334.     Frame frame;
  335.     XpmIcon *view = xmalloc (sizeof (*view), "CreateXpmIcon");
  336.     Rect rect;
  337.     Font font;
  338.     Font_string_dims fontdims;
  339.     XFontStruct *xfs;
  340.     XImage *ximage, *shapeimage;
  341.     GC gc;
  342.     static char *fontname = NULL;
  343.     int width, height;
  344.     int titlelen = strlen (title);
  345.  
  346.     screen = ScreenOfDisplay (dpy, 
  347.         (int) xv_get ((Xv_Screen) xv_get (mcframe, XV_SCREEN), SCREEN_NUMBER));
  348.         
  349.     colormap = XDefaultColormapOfScreen(screen);
  350.     memset (view, 0, sizeof (*view));
  351.     
  352.     frame = xv_create (mcframe, FRAME,
  353.         WIN_MAP, FALSE,
  354.         XV_X, x,
  355.         XV_Y, y,
  356.         XV_WIDTH, 32,
  357.         XV_HEIGHT, 32,
  358.         WIN_CONSUME_EVENTS, WIN_MOUSE_BUTTONS, WIN_UP_EVENTS, LOC_DRAG, NULL,
  359.         WIN_EVENT_PROC, XpmIconEvent,
  360.         WIN_CLIENT_DATA, view,
  361.         NULL);
  362.         
  363.     win = (Window) xv_get (frame, XV_XID);
  364.         
  365.     view->attributes.valuemask |= XpmReturnInfos;
  366.     view->attributes.valuemask |= XpmReturnPixels | XpmCloseness;
  367.     view->attributes.closeness = 40000;
  368.  
  369.     ErrorStatus = XpmReadFileToImage(dpy, iconname,
  370.                       &ximage, &shapeimage,
  371.                       &view->attributes);
  372.     if (ErrorStatus != XpmSuccess)
  373.     ErrorStatus = XpmCreateImageFromData(dpy, file_xpm,
  374.                           &ximage, &shapeimage,
  375.                           &view->attributes);
  376.                           
  377.     if (ErrorStatus != XpmSuccess) {
  378.         free (view);
  379.         xv_destroy_safe (frame);
  380.         XFlush (dpy);
  381.         return NULL;
  382.     }
  383.     
  384.     fontname = defaults_get_string ("mxc.iconfont", "Mxc.IconFont", "");
  385.     font = XV_NULL;
  386.     if (*fontname)
  387.         font = xv_find (mcframe, FONT, 
  388.             FONT_NAME, fontname,
  389.             NULL);
  390.     if (font == XV_NULL)
  391.         font = xv_get (mcframe, XV_FONT);
  392.     xv_get (font, FONT_STRING_DIMS, title, &fontdims);
  393.     xfs = (XFontStruct *) xv_get (font, FONT_INFO);
  394.     width = view->attributes.width;
  395.     if (view->attributes.width < fontdims.width)
  396.         view->attributes.width = fontdims.width;
  397.     height = view->attributes.height;
  398.     view->attributes.height += fontdims.height;
  399.     
  400.     view->pixmap = XCreatePixmap (dpy, win, view->attributes.width, 
  401.         view->attributes.height, ximage->depth);
  402.     gc = XCreateGC (dpy, view->pixmap, 0, NULL);
  403.     XSetForeground (dpy, gc, BlackPixelOfScreen (screen));
  404.     XFillRectangle (dpy, view->pixmap, gc, 0, 0, view->attributes.width,
  405.         view->attributes.height);
  406.     XPutImage (dpy, view->pixmap, gc, ximage, 0, 0, 
  407.         (view->attributes.width - width) / 2, 0, width, height);
  408.     XFreeGC (dpy, gc);
  409.     view->mask = XCreatePixmap (dpy, win, view->attributes.width,
  410.         view->attributes.height, 1);
  411.     gc = XCreateGC (dpy, view->mask, 0, NULL);
  412.     XSetFont (dpy, gc, xv_get (font, XV_XID));
  413.     XSetForeground (dpy, gc, 0);
  414.     XFillRectangle (dpy, view->mask, gc, 0, 0, view->attributes.width,
  415.         view->attributes.height);
  416.     XSetForeground (dpy, gc, 1);
  417.     if (shapeimage != NULL)
  418.         XPutImage (dpy, view->mask, gc, shapeimage, 0, 0, 
  419.             (view->attributes.width - width) / 2, 0, width, height);
  420.     else
  421.         XFillRectangle (dpy, view->mask, gc, 
  422.             (view->attributes.width - width) / 2, 0, width, height);
  423.     XDrawString (dpy, view->mask, gc, 
  424.         (view->attributes.width - fontdims.width) / 2, height + xfs->ascent,
  425.         title, titlelen);
  426.     XFreeGC (dpy, gc);
  427.     XDestroyImage (ximage);
  428.     if (shapeimage != NULL)
  429.         XDestroyImage (shapeimage);
  430.     
  431.     xv_set (frame,
  432.         XV_X, x - view->attributes.width / 2,
  433.         XV_Y, y - view->attributes.height / 2,
  434.         XV_WIDTH, view->attributes.width, 
  435.         XV_HEIGHT, view->attributes.height,
  436.         NULL);
  437.  
  438.     XSetWindowBackgroundPixmap(dpy, win, view->pixmap);
  439.  
  440.     if (view->mask)
  441.     XShapeCombineMask(dpy, win, ShapeBounding, 0, 0,
  442.               view->mask, ShapeSet);
  443.  
  444.     XClearWindow(dpy, win);
  445.     
  446.     rect.r_left = 0;
  447.     rect.r_top = 0;
  448.     rect.r_width = view->attributes.width;
  449.     rect.r_height = view->attributes.height;
  450.     
  451.     xv_create (frame, DROP_SITE_ITEM,
  452.         DROP_SITE_EVENT_MASK, DND_ENTERLEAVE,
  453.         DROP_SITE_REGION, &rect,
  454.         NULL);
  455.     xv_set (frame, 
  456.         XV_KEY_DATA, KEY_DATA_SELREQ,
  457.             xv_create (frame, SELECTION_REQUESTOR, NULL),
  458.         NULL);
  459.  
  460.     xv_set (frame,
  461.         WIN_MAP, TRUE,
  462.         NULL);
  463.         
  464.     view->frame = frame;
  465.     
  466.     return view;
  467. }
  468.  
  469. void DeleteXpmIcon (XpmIcon *view)
  470. {
  471.     if (view->pixmap) {
  472.     XFreePixmap(dpy, view->pixmap);
  473.     if (view->mask)
  474.         XFreePixmap(dpy, view->mask);
  475.  
  476.     XFreeColors(dpy, colormap,
  477.             view->attributes.pixels, view->attributes.npixels, 0);
  478.  
  479.     XpmFreeAttributes(&view->attributes);
  480.     }
  481.     if (view->filename)
  482.         free (view->filename);
  483.     free (view);
  484. }
  485.  
  486. #endif
  487.